﻿using Model.Domain.Extra;
using Model.Domain.Language;
using System.Data;

namespace Service.Base
{
    public class EnumHelperService : IEnumHelperService
    {
        private string _TenantKey;

        public bool IsValueInEnum<T>(int value)
        {
            return Enum.IsDefined(typeof(T), value);
        }

        public string GetDescription<T>(T val, string tenantKey = "") where T : struct, Enum
        {
            if (!string.IsNullOrEmpty(tenantKey))
            {
                _TenantKey = tenantKey;
            }

            _ = Enum.GetNames(typeof(T));

            if (IsValueInEnum<T>((int)(object)val) == false)
            {
                return string.Empty;
            }
            var field = val.GetType().GetField(val.ToString());
            if (_TenantKey == "tw")
            {
                var customAttribute = Attribute.GetCustomAttribute(field, typeof(Tw));
                return customAttribute == null ? val.ToString() : ((Tw)customAttribute).Data;
            }
            else if (_TenantKey == "en")
            {
                var customAttribute = Attribute.GetCustomAttribute(field, typeof(En));
                return customAttribute == null ? val.ToString() : ((En)customAttribute).Data;
            }
            else
            {
                return val.ToString();
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public List<RM_Select> GetSelect4Enum<T>() where T : struct, Enum
        {
            var result = new List<RM_Select>();
            var twType = typeof(Tw);
            var enType = typeof(En);

            var hasAction = typeof(HasAction);

            var values = Enum.GetValues(typeof(T));
            var names = Enum.GetNames(typeof(T));

            for (int i = 0; i < values.Length; i++)
            {
                RM_Select itemInfo = new()
                {
                    Key = (int)values.GetValue(i)
                };

                var field = typeof(T).GetField(names[i]);
                var attributes = Attribute.GetCustomAttributes(field);

                if (_TenantKey == "tw")
                {
                    var customAttribute = attributes.FirstOrDefault(a => a.GetType() == twType);
                    if (customAttribute != null)
                    {
                        itemInfo.Value = ((Tw)customAttribute).Data;
                    }
                }
                else if (_TenantKey == "en")
                {
                    var customAttribute = attributes.FirstOrDefault(a => a.GetType() == enType);
                    if (customAttribute != null)
                    {
                        itemInfo.Value = ((En)customAttribute).Data;
                    }
                }

                if (string.IsNullOrEmpty(itemInfo.Value))
                {
                    itemInfo.Value = names[i];
                }

                var hasActionAttribute = attributes.FirstOrDefault(a => a.GetType() == hasAction);
                if (hasActionAttribute == null)
                {
                    itemInfo.HasAction = false;
                }
                else
                {
                    itemInfo.HasAction = ((HasAction)hasActionAttribute).Data;
                }

                result.Add(itemInfo);
            }

            return result;
        }

        public void SetTenant(string tenantKey)
        {
            _TenantKey = tenantKey;
        }

        public List<RM_Select> GetSelect4Enum<T>(List<int> selectValus, List<int> IgnoreValues) where T : struct, Enum
        {
            var result = new List<RM_Select>();
            var twType = typeof(Tw);
            var enType = typeof(En);

            var values = Enum.GetValues(typeof(T));
            if (selectValus.Count > 0)
            {
                values = values.Length > 0 ? values.Cast<int>().Where(o => selectValus.Contains(o)).ToArray() : Array.Empty<int>();
            }
            if (IgnoreValues.Count > 0)
            {
                values = values.Length > 0 ? values.Cast<int>().Where(o => !IgnoreValues.Contains(o)).ToArray() : Array.Empty<int>();
            }
            var names = Enum.GetNames(typeof(T));

            for (int i = 0; i < values.Length; i++)
            {
                RM_Select itemInfo = new()
                {
                    Key = (int)values.GetValue(i)
                };

                itemInfo.Value = GetDescription<T>((T)Enum.ToObject(typeof(T), itemInfo.Key));

                result.Add(itemInfo);
            }

            return result;
        }
    }
}